﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KC.ExtensionMethods
{
	/// <summary>extension methods on strings</summary>
	public static class Strings
	{
		/// <summary>How many times does this character exist in this string?</summary>
		/// <param name="str">Containing string</param>
		/// <param name="c">Char to find</param>
		/// <returns>Number of instances of char in string</returns>
		public static int CountOf(this string str, char c)
		{
			if (string.IsNullOrEmpty(str))
				return 0;
			int count = 0;
			for (int i = 0; i < str.Length; i++)
				if (str[i] == c)
					count++;
			return count;
		}
		/// <summary>How many times does this string exist in this string?</summary>
		/// <param name="str">Containing string</param>
		/// <param name="Target">String to find</param>
		/// <returns>Number of instances of string in string</returns>
		public static int CountOf(this string str, string Target)
		{
			if (string.IsNullOrEmpty(str)) return 0;
			if (string.IsNullOrEmpty(Target)) throw new ArgumentNullException("Target");

			int count = 0;
			for (int i = 0; i < str.Length; i++)
				if (str.Substring(i).StartsWith(Target))
					count++;
			return count;
		}
		/// <summary>Wraps a string every n characters.</summary>
		/// <param name="str">String to wrap</param>
		/// <param name="WrapPos">Where to wrap each line</param>
		/// <returns>Wrapped string</returns>
		public static string WrapAt(this string str, int WrapPos)
		{
			if (string.IsNullOrEmpty(str))
				throw new ArgumentNullException("str", "Cannot wrap a null string");
			str = str.Replace("\r", "").Replace("\n", "");

			if (str.Length <= WrapPos)
				return str;

			for (int i = str.Length; i >= 0; i--)
				if (i % WrapPos == 0 && i > 0 && i != str.Length)
					str = str.Insert(i, "\r\n");
			return str;
		}
		/// <summary>Gets the length of the longest line in a string containing many lines</summary>
		/// <param name="str">String to parse</param>
		/// <returns>Length of the longest line</returns>
		public static int GetMaxLineLength(this string str)
		{
			if (string.IsNullOrEmpty(str))
				return 0;
			string[] lines = str.Replace("\r", "").Split('\n');
			int max = 0;
			foreach (string line in lines)
				if (line.Length > max)
					max = line.Length;
			return max;
		}
		/// <summary>Truncates a string if longer than n characters.</summary>
		/// <param name="str">String to truncate</param>
		/// <param name="MaxLength">Where to cut it off</param>
		/// <returns>Truncated string if longer, else full string</returns>
		public static string TruncateIfLonger(this string str, int MaxLength)
		{
			if (string.IsNullOrEmpty(str)) return str;
			if (str.Length > MaxLength)
				return str.Substring(0, MaxLength);
			else
				return str;
		}

		/// <summary>Reports the indices of all the occurences of the specified string in the current string.</summary>
		/// <param name="str">this string</param>
		/// <param name="value">String to search for</param>
		/// <returns>Array of all indices where the specified value occurs in this string.</returns>
		public static int[] IndexesOf(this string str, string value)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value");
			List<int> indices = new List<int>();
			for (int i = 0; i < str.Length; i++)
				if (str.Substring(i).StartsWith(value))
					indices.Add(i);
			return indices.ToArray();
		}
		/// <summary>Reports the indices of all the occurences of the specified char in the current string.</summary>
		/// <param name="str">this string</param>
		/// <param name="value">char to search for</param>
		/// <returns>Array of all indices where the specified value occurs in this string.</returns>
		public static int[] IndexesOf(this string str, char value)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			List<int> indices = new List<int>();
			for (int i = 0; i < str.Length; i++)
				if (str[i] == value)
					indices.Add(i);
			return indices.ToArray();
		}

		public static bool ContainsAny(this string str, string[] values)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			foreach (string value in values)
				if (str.Contains(value)) return true;
			return false;
		}
		public static bool ContainsAny(this string str, List<string> values)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			return str.ContainsAny(values.ToArray());
		}
		public static bool ContainsAny(this string str, string[] values, bool CaseSensitive)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			if (CaseSensitive) return str.ContainsAny(values);
			str = str.ToLower();
			foreach (string value in values)
				if (str.Contains(value.ToLower())) return true;
			return false;
		}
		public static bool ContainsAny(this string str, List<string> values, bool CaseSensitive)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			return str.ContainsAny(values.ToArray(), CaseSensitive);
		}

		public static bool EndsWithAny(this string str, char[] values)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			foreach (char value in values)
				if (str.EndsWith(value.ToString())) return true;
			return false;
		}
		public static bool EndsWithAny(this string str, string[] values)
		{
			if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str");
			if (values == null) throw new ArgumentNullException("values");

			foreach (string value in values)
				if (str.EndsWith(value)) return true;
			return false;
		}

	}
}
